/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/* nixonFTP
 * FTP client version 0.1
 * Copyright (C) 2010 NIXON Development Corporation.
 * All rights reserved.
 * http://members.shaw.ca/nixon.com
 */
package nixonftp.ui;

import nixonftp.*;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
import javax.swing.border.Border;
import nixonftp.list.NXDefaultListModel;


public class NXFilterDialog extends JDialog implements ItemListener, ActionListener, MouseListener {

	JPanel cards;
	JComboBox dateUnits;
	JComboBox dateRange;
	JSpinner dateSpinner;
	JLabel colorLabel;
	JComboBox sizeUnits;
	JComboBox sizeRange;
	JTextField sizeValue;
	JComboBox cardSelector;
	JComboBox actionSelector;
	JList list;
	JButton addFilter;
	JButton removeFilter;
	Color color = Color.WHITE;
	final static String strDate = "Date";
	final static String strSize = "Size";
	private final JPanel common;
	private Border colorBorder = BorderFactory.createLineBorder(Color.gray);
	private Border colorBorderFocus = BorderFactory.createMatteBorder(2, 2, 2, 2, new Color(0, 128, 255));

	public NXFilterDialog(JFrame parent) {
		super(parent);
		setTitle("Filters");
		String[] items = {strDate, strSize};
		Container contentPane = this.getContentPane();
		contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
		setPreferredSize(new Dimension(430, 320));
		//this.setResizable(false);

		JPanel datePanel = new JPanel();
		datePanel.add(new JLabel("Files modified "));
		dateRange = new JComboBox(new String[] {"within","before"});
		datePanel.add(dateRange);
		datePanel.add(new JLabel(" the past "));
		dateSpinner = new JSpinner();
		dateSpinner.setModel(new SpinnerNumberModel(0, 0, null, 1));
		dateSpinner.setPreferredSize(new Dimension(64, 25));
		datePanel.add(dateSpinner);

		String[] dateUnitItems = {"seconds", "minutes", "hours", "days", "weeks", "months", "years"};
		dateUnits = new JComboBox(dateUnitItems);
		datePanel.add(dateUnits);

		JPanel sizePanel = new JPanel();
		sizePanel.add(new JLabel("Files with a size "));
		sizeRange = new JComboBox(new String[]{"less than", "equal to", "greater than"});
		sizePanel.add(sizeRange);
		sizeValue = new JTextField();
		sizeValue.setPreferredSize(new Dimension(96,25));
		sizePanel.add(sizeValue);
		sizeUnits = new JComboBox(new String[]{"bytes", "KB", "MB", "GB"});
		sizePanel.add(sizeUnits);

		JPanel selectPanel = new JPanel();
		selectPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
		selectPanel.setMaximumSize(new Dimension(460,130));
		selectPanel.setLayout(new GridLayout(2,2));
		selectPanel.add(new JLabel("Add filter based on:"), BorderLayout.LINE_START);
		cardSelector = new JComboBox(items);
		cardSelector.setEditable(false);
		cardSelector.addItemListener(this);
		selectPanel.add(cardSelector);
		actionSelector = new JComboBox(new String[] {"Label with color", "Show only", "Hide"});
		actionSelector.setEditable(false);
		actionSelector.addItemListener(this);
		selectPanel.add(new JLabel("Action:"));
		selectPanel.add(actionSelector);
		add(selectPanel);

		cards = new JPanel(new CardLayout());
		cards.add(datePanel, strDate);
		cards.add(sizePanel, strSize);
		cards.setBorder(BorderFactory.createTitledBorder(""));
		cards.setMaximumSize(new Dimension(460,200));
		add(cards);

		common = new JPanel();
		common.add(new JLabel("with this color: "));
		colorLabel = new JLabel();
		colorLabel.setFocusable(true);
		colorLabel.addFocusListener(new ColorFocusListener());
		colorLabel.addKeyListener(new ColorKeyListener());
		colorLabel.setPreferredSize(new Dimension(75,20));
		colorLabel.setBackground(color);
		colorLabel.setBorder(colorBorder);
		colorLabel.setOpaque(true);
		colorLabel.addMouseListener(this);
		common.add(colorLabel);
		add(common);

		JPanel actions = new JPanel();
		SpringLayout layout = new SpringLayout();
		actions.setLayout(layout);
		addFilter = new JButton("Add Filter");
		addFilter.setDefaultCapable(true);
		addFilter.addActionListener(this);
		getRootPane().setDefaultButton(addFilter);
		actions.add(addFilter);
		layout.putConstraint(SpringLayout.EAST, addFilter,
                     -12,
                     SpringLayout.EAST, actions);
		list = new JList();
		list.setCellRenderer(new FilterRenderer());
		JScrollPane listScroll = new JScrollPane(list);
		NXDefaultListModel listModel = new NXDefaultListModel();
		list.setModel(listModel);
		actions.add(listScroll);
		layout.putConstraint(SpringLayout.NORTH, listScroll,
                     33,
                     SpringLayout.NORTH, actions);
		layout.putConstraint(SpringLayout.SOUTH, actions,
							0,
                     SpringLayout.SOUTH, listScroll);
		layout.putConstraint(SpringLayout.EAST, actions,
                     0,
                     SpringLayout.EAST, listScroll);
		layout.putConstraint(SpringLayout.WEST, actions,
                     0,
                     SpringLayout.WEST, listScroll);
		removeFilter = new JButton("Remove");
		layout.putConstraint(SpringLayout.WEST, removeFilter,
                     12,
                     SpringLayout.WEST, actions);
		actions.add(removeFilter);
		actions.setOpaque(false);
		//removeFilter.setMaximumSize(new Dimension(96,25));
		removeFilter.addActionListener(this);

		add(actions);

		pack();
	}

	private class ColorFocusListener implements FocusListener {
		public void focusGained(FocusEvent e) {
			colorLabel.setBorder(colorBorderFocus);
		}

		public void focusLost(FocusEvent e) {
			colorLabel.setBorder(colorBorder);
		}
	}

	private class ColorKeyListener implements KeyListener {

		public void keyTyped(KeyEvent e) {
		}

		public void keyPressed(KeyEvent e) {
		}

		public void keyReleased(KeyEvent e) {
			int keyCode = e.getKeyCode();
			if (keyCode == KeyEvent.VK_SPACE) {
				showColorDialog();
			}
		}

	}

	public void setFilters(NXFilter[] filters) {
		if (filters == null) return;
		NXDefaultListModel lm = (NXDefaultListModel) list.getModel();
		for (int x = 0; x < filters.length; x++) {
			lm.addElement(filters[x]);
		}
		list.setModel(lm);
	}
	
	public void itemStateChanged(ItemEvent e) {
		Object source = e.getSource();
		if (source.equals(cardSelector)) {
			CardLayout cl = (CardLayout) (cards.getLayout());
			String s = (String) e.getItem();
			cl.show(cards, s);
		} else if (source.equals(actionSelector)) {
			int idx = ((JComboBox) source).getSelectedIndex();
			common.setVisible(idx == 0);
		}
	}

	public void actionPerformed(ActionEvent e) {
		Object source = e.getSource();
		NXDefaultListModel lm = (NXDefaultListModel) list.getModel();
		if (source.equals(addFilter)) {
			int type = cardSelector.getSelectedIndex();
			int unit = 0;
			long value = 0;
			int range = 0;
			int action = actionSelector.getSelectedIndex();
			switch (type) {
				case NXFilter.DATE:
					unit = dateUnits.getSelectedIndex();
					range = dateRange.getSelectedIndex();
					value = Long.valueOf(dateSpinner.getValue().toString());
					break;
				case NXFilter.SIZE:
					unit = sizeUnits.getSelectedIndex();
					range = sizeRange.getSelectedIndex();
					value = Long.valueOf(sizeValue.getText());
					break;
			}

			NXFilter filter = new NXFilter(type, action, range, value, unit);
			filter.setColor(color);

			lm.addElement(filter);
		} else if (source.equals(removeFilter)) {
			int selected = list.getSelectedIndex();
			if (selected != -1) {
				lm.remove(selected);
				if (selected > 1) {
					list.setSelectedIndex(selected - 1);
				} else {
					list.setSelectedIndex(0);
				}
			}
		}
	}

	public NXFilter[] getFilters() {
		NXDefaultListModel lm = (NXDefaultListModel) list.getModel();
		int size = lm.getSize();
		NXFilter[] filters = new NXFilter[lm.getSize()];
		for (int x = 0; x < size; x++) {
			filters[x] = (NXFilter) lm.get(x);
		}
		return filters;
	}

	private void showColorDialog() {
		color = JColorChooser.showDialog(
                     this,
                     "Choose Filter Color",
                     color);
		colorLabel.setBackground(color);
	}

	public void mouseClicked(MouseEvent e) {
		showColorDialog();
	}

	public void mousePressed(MouseEvent e) {
	}

	public void mouseReleased(MouseEvent e) {
	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}
}

class FilterRenderer extends JLabel implements ListCellRenderer {

	static Color listForeground,
					listBackground,
					listSelectionForeground,
					listSelectionBackground;

	static {
        UIDefaults uid = UIManager.getLookAndFeel().getDefaults();
		  listBackground = uid.getColor("List.background");
        listForeground = uid.getColor("List.foreground");
		  listSelectionBackground = uid.getColor("List.selectionBackground");
        listSelectionForeground = uid.getColor("List.selectionForeground");
    }

	static Border defaultBorder = BorderFactory.createEmptyBorder(2, 6, 2, 6);
	static Border selectedBorder = BorderFactory.createCompoundBorder(
					BorderFactory.createLineBorder(listSelectionBackground),
					defaultBorder
			  );
	
	public FilterRenderer() {
		setOpaque(true);
		setBorder(defaultBorder);
	}

	public JLabel getListCellRendererComponent(JList list, Object value,
			  int index, boolean isSelected, boolean cellHasFocus) {
		/*JLabel c = (JLabel) super.getListCellRendererComponent(list,
				  value,
				  index,
				  isSelected,
				  cellHasFocus);*/
		//change the path accordingly
		NXFilter filter = (NXFilter) value;
		if (filter.color != null) {
			setBackground(filter.color);
			setForeground(NXFormat.invertColor(filter.color));
		} else {
			setBackground(listBackground);
		}
		if (isSelected) {
			setBorder(selectedBorder);
		} else {
			setBorder(defaultBorder);
		}
		setText(value.toString());
		invalidate();
		return this;
	}

}